import {
  Body,
  Controller,
  Inject,
  Post,
  HttpException,
  HttpStatus,
  Get,
  Param,
  ParseIntPipe,
  Put,
  Delete,
} from '@nestjs/common';
import { UserService } from './User.service';
import { LoginDto, CodeLoginDto, RegisterDto } from '@/dto/UserLogin.dto';
import UpdateUserInfoDto from '@/dto/UpdateUserInfo.dto';
import { CheckUser, UserInfo } from '@/decorator/index.decorator';

import { ConfigService } from '@nestjs/config';
import { JwtService } from '@nestjs/jwt';
import { RedisService } from '@/redis/redis.service';

@Controller('user')
export class UserController {
  @Inject(UserService)
  private readonly userService: UserService;

  @Inject(ConfigService)
  private readonly configService: ConfigService;

  @Inject(JwtService)
  private readonly jwtService: JwtService;

  @Inject(RedisService)
  private readonly redisService: RedisService;

  fommatStar(item) {
    item.community_img = item.community_img.map((i: any) => i.img);
    item.username = item.User.username;
    item.avatar = item.User.avatar;

    // eslint-disable-next-line
    const { updatedAt, User, ...rest } = item;
    return rest;
  }

  fommatCollect(item) {
    item.scenic_img = item.scenic_img.map((i: any) => i.img);
    // eslint-disable-next-line
    const { createdAt, updatedAt, ...rest } = item;
    return rest;
  }

  fommatComment(item) {
    item.username = item.User.username;
    item.avatar = item.User.avatar;
    // eslint-disable-next-line
    const { updatedAt, User, userId, communityId, ...rest } = item;
    return rest;
  }

  @Post('login')
  async login(@Body() userInfo: LoginDto) {
    const user = await this.userService.login(userInfo);
    if (!user) {
      throw new HttpException('账号或密码错误', HttpStatus.BAD_REQUEST);
    }
    const accessToken = this.jwtService.sign(
      {
        userId: user.id,
        phone: user.phone,
      },
      {
        expiresIn: this.configService.get('jwt.access_token_expires') || '30m',
      },
    );
    return accessToken;
  }

  @Post('code')
  async codeLogin(@Body() userInfo: CodeLoginDto) {
    const { phone, code } = userInfo;
    const user = await this.userService.codeLogin(phone);
    if (!user) {
      throw new HttpException('用户不存在, 请先注册', HttpStatus.BAD_REQUEST);
    }
    const redisCode = await this.redisService.get(phone);
    if (redisCode !== code) {
      throw new HttpException('验证码错误', HttpStatus.BAD_REQUEST);
    }

    await this.redisService.del(phone);

    const accessToken = this.jwtService.sign(
      {
        userId: user.id,
        phone: user.phone,
      },
      {
        expiresIn: this.configService.get('jwt.access_token_expires') || '30m',
      },
    );
    return accessToken;
  }

  @Get('valid/:phone')
  async validPhone(@Param('phone') phone: string) {
    const user = await this.userService.validPhone(phone);
    return user && '该手机号已被注册';
  }

  @Post('register')
  async register(@Body() userInfo: RegisterDto) {
    await this.userService.register(userInfo);
    return '注册成功';
  }

  @Post('sendCode')
  async sendCode(@Body('phone') phone: string) {
    const redisTime = await this.redisService.get(phone + '_time');
    if (redisTime && new Date().getTime() - +redisTime < 60 * 1000) {
      throw new HttpException('发送频繁，请稍后再试', HttpStatus.BAD_REQUEST);
    }

    const code = Math.random().toString().slice(2, 8);
    await this.redisService.set(phone, code, 60 * 5);
    await this.redisService.set(phone + '_time', new Date().getTime(), 60);
    return code;
  }

  @Get('collect/:scenicId')
  @CheckUser()
  async collectScenic(
    @UserInfo('userId') userId: number,
    @Param('scenicId', ParseIntPipe) scenicId: number,
  ) {
    const res = await this.userService.collectScenic(userId, scenicId);
    return res;
  }

  @Get('star/:dynamicId')
  @CheckUser()
  async starDynamic(
    @UserInfo('userId') userId: number,
    @Param('dynamicId', ParseIntPipe) dynamicId: number,
  ) {
    const res = await this.userService.starDynamic(userId, dynamicId);
    return res;
  }

  @Get()
  @CheckUser()
  async getUserInfo(@UserInfo('userId') userId: number) {
    const res = await this.userService.getUserInfo(userId);
    return res;
  }

  @Put('update')
  @CheckUser()
  async updateUserInfo(@Body() userInfo: UpdateUserInfoDto) {
    const res = await this.userService.updateUserInfo(userInfo);
    return res;
  }

  @Post('publish')
  @CheckUser()
  async publishDynamic(@UserInfo('userId') userId, @Body() dynamicInfo: any) {
    const { content, img } = dynamicInfo;
    const res = await this.userService.publishDynamic(userId, content, img);
    return res;
  }

  @Post('getStar')
  @CheckUser()
  async getStar(@UserInfo('userId') userId, @Body() data: any) {
    const { pageNum, pageSize } = data;
    const res = await this.userService.getMyStarDynamic(
      userId,
      pageNum,
      pageSize,
    );
    res.list = res.list.map((item) => this.fommatStar(item.community));
    return res;
  }

  @Post('getCollect')
  @CheckUser()
  async getCollect(@UserInfo('userId') userId, @Body() data: any) {
    const { pageNum, pageSize } = data;
    const res = await this.userService.getMyCollectScenic(
      userId,
      pageNum,
      pageSize,
    );
    res.list = res.list.map((item) => this.fommatCollect(item.scenic));
    return res;
  }

  @Post('comment')
  async getCommentList(@Body() data: any) {
    const { communityId, pageNum, pageSize } = data;
    const res = await this.userService.getCommentList(
      communityId,
      pageNum,
      pageSize,
    );
    res.list = res.list.map((item) => this.fommatComment(item));
    return res;
  }

  @Post('postComment')
  @CheckUser()
  async postComment(@UserInfo('userId') userId, @Body() data: any) {
    const { communityId, content } = data;
    const res = await this.userService.postComment(
      communityId,
      userId,
      content,
    );
    return res;
  }

  @Delete('dynamic/:dynamicId')
  @CheckUser()
  async deleteDynamic(
    @UserInfo('userId') userId,
    @Param('dynamicId', ParseIntPipe) dynamicId: number,
  ) {
    const res = await this.userService.deleteDynamic(userId, dynamicId);
    return res;
  }
}
